﻿using System;
using System.Collections.Generic;
using System.Text;
using Google.GData.Contacts;
using System.Xml;
using System.Drawing;
using Google.GData.Client;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;

namespace DataLoad.iContact.WinClient
{
    public class DLContact : IComparable<DLContact>, IEquatable<DLContact>
    {
        public static ContactsService Service;

        public static frmMain MainForm;

        public DLContact(ContactEntry contact, NameDisplayType nameOrder, bool newContact)
        {
            _contact = contact;
            _nameOrder = nameOrder;
            _newContact = newContact;
            _parser = new NameParser(contact.Title.Text);
            _contactChanged = newContact;
        }

        private bool _newContact;

        public bool NewContact
        {
            get
            {
                return _newContact;
            }
            set
            {
                _newContact = value;
            }
        }

        private bool _pictureChanged = false;

        public bool PictureChanged
        {
            get
            {
                return _pictureChanged;
            }
            set
            {
                _pictureChanged = value;
            }
        }

        private ContactEntry _contact;

        public ContactEntry Contact
        {
            get
            {
                return _contact;
            }
        }

        private Image _picture;

        public Image Picture
        {
            get
            {
                try
                {
                    if ((_picture == null) && (_pictureAvailable) && (Contact.PhotoUri != null))
                    {
                        IGDataRequest req = Service.RequestFactory.CreateRequest(GDataRequestType.Query, Contact.PhotoUri);
                        req.Execute();
                        _picture = new Bitmap(req.GetResponseStream());
                        _pictureChanged = false;
                    }
                }
                catch (Exception exc)
                {
                    MainForm.ShowError(exc.Message, "Unable to retrieve picture");
                }

                return _picture;
            }
            set
            {
                _picture = value;

                if (_picture == null)
                {
                    DeletePicture();
                    _pictureAvailable = false;
                }

                _pictureChanged = true;
            }
        }

        private void SavePicture()
        {
            using (MemoryStream st = new MemoryStream())
            {
                _picture.Save(st, ImageFormat.Jpeg);
                st.Position = 0;

                Service.Update(Contact.PhotoEditUri, st, "image/jpeg", null);

                _pictureChanged = false;
            }
        }

        public void DeletePicture()
        {
            Service.Delete(Contact.PhotoEditUri);
        }

        public void Save()
        {
            try
            {
                if (_newContact)
                {
                    Uri feedUri = new Uri(ContactsQuery.CreateContactsUri("default"));
                    ContactEntry createdEntry = (ContactEntry)Service.Insert(feedUri, Contact);
                    _newContact = false;

                    if (_pictureChanged)
                    {
                        SavePicture();
                    }
                }
                else
                {
                    Contact.Update();
                    if (_pictureChanged)
                    {
                        SavePicture();
                    }
                }

                _contactChanged = false;
            }
            catch (Exception exc)
            {
                MainForm.ShowMessage(exc.Message, "Error", MessageBoxIcon.Error, MessageBoxButtons.OK);
            }
        }

        /// <summary>
        /// Loads this contact from Google
        /// </summary>
        public void Load()
        {
            try
            {
                ContactsQuery query = new ContactsQuery(_contact.SelfUri.Content);
                ContactsFeed feed = Service.Query(query);
                _contact = (ContactEntry)feed.Entries[0];
            }
            catch (Exception exc)
            {
                MainForm.ShowError(exc.Message, "Unable to retrieve the contact");
            }
        }

        private bool _pictureAvailable = true;

        private bool _contactChanged = true;

        public bool ContactChanged
        {
            get
            {
                return _contactChanged;
            }
            set
            {
                _contactChanged = value;
            }
        }

        public bool HasNotes
        {
            get
            {
                return ((_contact != null) &&
                        (_contact.Content != null) &&
                        (!string.IsNullOrEmpty(_contact.Content.Content)));
            }
        }

        public string Notes
        {
            get
            {
                if (HasNotes)
                {
                    return _contact.Content.Content;
                }
                else
                {
                    return string.Empty;
                }
            }

            set
            {
                _contact.Content.Content = value;
                ContactChanged = true;
            }
        }

        private ContactResultType _resultType = ContactResultType.NotSearchResult;

        public ContactResultType ResultType
        {
            get
            {
                return _resultType;
            }
            set
            {
                _resultType = value;
            }
        }

        public bool HasTitle
        {
            get
            {
                return ((_contact != null) && (_contact.Title != null) && (!string.IsNullOrEmpty(_contact.Title.Text)));
            }
        }

        private NameDisplayType _nameOrder = NameDisplayType.NoChange;

        public NameDisplayType NameOrder
        {
            get
            {
                return _nameOrder;
            }
            set
            {
                _nameOrder = value;
            }
        }

        private NameParser _parser;

        public NameParser Parser
        {
            get
            {
                return _parser;
            }
        }

        public override string ToString()
        {
            if (_contact != null)
            {
                if (HasTitle)
                {
                    switch (_nameOrder)
                    {
                        case NameDisplayType.NoChange:
                            return _contact.Title.Text;

                        case NameDisplayType.LastFirst:
                            return string.Format("{0} {1}", _parser.LastName, _parser.FirstName);

                        case NameDisplayType.FirstLast:
                            return string.Format("{0} {1}", _parser.FirstName, _parser.LastName);

                        default:
                            throw new ApplicationException("Invalid name order");
                    }
                }
                else
                {
                    if (_contact.Emails.Count > 0)
                    {
                        return _contact.Emails[0].Address;
                    }
                    else
                    {
                        return string.Empty;
                    }
                }
            }
            else
            {
                return string.Empty;
            }
        }

        public bool IsDuplicate(DLContact contact)
        {
            return ((contact.Contact != null) && (contact.Contact.Title == Contact.Title));
        }

        /*public void AddToNode(XmlElement node)
        {
            XmlElement item = node.OwnerDocument.CreateElement("contact");
            XmlAttribute title = node.OwnerDocument.CreateAttribute("title");
            title.Value = _contact.Title.Text;
            item.Attributes.Append(title);

            node.AppendChild(node);
        }

        public void LoadFromNode(XmlElement node)
        {

        }*/

        #region IComparable<DLContact> Members

        public int CompareTo(DLContact other)
        {
            if ((_contact != null) && (other.Contact != null))
            {
                // compare match results first
                if (_resultType == other.ResultType)
                {
                    return ToString().CompareTo(other.ToString());
                }
                else
                {
                    return _resultType.CompareTo(other.ResultType);
                }
            }
            else
            {
                return 0;
            }
        }

        #endregion

        #region IEquatable<DLContact> Members

        public bool Equals(DLContact other)
        {
            return (other.Contact.SelfUri.Content.Equals(this.Contact.SelfUri.Content));
        }

        #endregion
    }
}
